<template>
  <div class="image-upload" :style="containerStyle">
    <n-upload
      :custom-request="customRequest"
      :max="1"
      :accept="accept"
      @change="handleChange"
      @remove="handleRemove"
      list-type="image-card"
    >
      <template #default>
        <div class="upload-trigger">
          <n-icon :size="iconSize">
            <cloud-upload-outlined />
          </n-icon>
          <div v-if="!compact" class="upload-text">点击上传</div>
        </div>
      </template>
      <template #file-list="{ files }">
        <div v-if="props.value" class="preview-image">
          <img :src="props.value" :style="imageStyle" />
        </div>
      </template>
    </n-upload>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { NIcon, NUpload } from 'naive-ui'
import { CloudUploadOutlined } from '@vicons/antd'
import request from '@/utils/request'

const props = defineProps({
  value: {
    type: String,
    default: ''
  },
  accept: {
    type: String,
    default: 'image/jpeg,image/png,image/gif'
  },
  size: {
    type: Number,
    default: 100
  },
  compact: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['update:value', 'change'])

// 计算容器样式
const containerStyle = computed(() => ({
  '--upload-size': `${props.size}px`
}))

// 计算图片样式
const imageStyle = computed(() => ({
  width: `${props.size}px`,
  height: `${props.size}px`,
  objectFit: 'cover'
}))

// 计算图标大小
const iconSize = computed(() => props.compact ? props.size / 3 : 20)

// 自定义上传请求
const customRequest = async ({ file }) => {
  try {
    const formData = new FormData()
    formData.append('file', file.file)
    
    const res = await request.post('/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
    
    emit('update:value', res.url)
    emit('change', res.url)
    
    return {
      status: 'finished',
      url: res.url
    }
  } catch (error) {
    return {
      status: 'error',
      message: '上传失败'
    }
  }
}

// 处理文件改变
const handleChange = (options) => {
  const { file } = options
  if (file.status === 'finished') {
    emit('update:value', file.url)
    emit('change', file.url)
  }
}

// 处理文件移除
const handleRemove = () => {
  emit('update:value', '')
  emit('change', '')
}
</script>

<style lang="scss" scoped>
.image-upload {
  :deep(.n-upload-trigger) {
    width: var(--upload-size);
    height: var(--upload-size);
    border: 1px dashed #d9d9d9;
    border-radius: 4px;
    
    &:hover {
      border-color: var(--primary-color);
    }
  }

  .upload-trigger {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    cursor: pointer;
    
    .upload-text {
      margin-top: 4px;
      font-size: 12px;
      color: #666;
    }
    
    .n-icon {
      color: #999;
    }

    &:hover {
      .n-icon, .upload-text {
        color: var(--primary-color);
      }
    }
  }

  .preview-image {
    width: var(--upload-size);
    height: var(--upload-size);
    border-radius: 4px;
    overflow: hidden;
    border: 1px solid #eee;

    img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }
}
</style> 